package demo01;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/*
 *  读取数据的原理（内存 --> 硬盘）：
 *      java程序 --> JVM（java虚拟机） --> OS（操作系统） --> OS调用读取数据的方法 --> 读取文件
 * 
 *  FileInputStream类的构造方法；
 *      FileInputStream(File file)：创建文件字节输入流，用于从指定的File对象读取字节
 *      FileInputStream(String name)：创建文件字节输入流，用于从路径字符串指定的文件读取字节
 * 
 *  FileInputStream类的常用方法；
 *      public void close()：关闭文件字节输入流，释放资源
 *      public int read()：读取一个字节，提升为int类型并返回，读取到文件末尾会返回-1
 *      public int read(byte[] b)：读取一组字节，读取字节的数量取决于参数数组的大小，读取到的内容会存储到参数数组中，返回成功读取到的字节个数，没有读取到新内容则会返回-1
 * 
 *  文件字节输入流的使用步骤：
 *     1. 创建一个FileInputStream对象，构造方法中绑定要读取的数据源文件的路径
 *     2. 调用FileInputStream对象的方法read，读取文件
 *     3. 释放资源
 */
public class Demo02FileInputStream {
    public static void main(String[] args) throws IOException {
        /*
         *  FileInputStream构造方法执行了以下几件事：
         *      1. 创建了一个文件字节输入流对象fileInputStreamC
         *      2. 根据构造参数的路径打开文件"c.txt"，路径可以是文件类型，也可以是路径名的字符串
         *      3. 把fileInputStreamC指向打开的文件"c.txt"，创建了一个文件内容指针，指向该文件最开始的位置
         *  FileInputStream构造方法会抛出FileNotFoundException文件拒绝访问异常，可以声明处理
         *  读取方法会抛出IOException，是FileNotFoundException的父类，可以通过直接让方法声明IO异常来完成处理
         */
        FileInputStream fileInputStreamC = new FileInputStream(new File("file\\c.txt"));

        /*
         *  read()方法有空参和带参两种使用方式：
         *      空参：代表读取一个字节的数据，该方法执行了以下几件事：
         *          1. 获取到文件内容指针当前指向的字节，将该字节提升为int类型并返回
         *              如果需要使用该字节的字符形式表示，可以使用(char)强制转换为字符
         *          2. 文件的内容指针向后移动一个字节，用于下一次进行读取操作
         *          3. 如果文件内容指针指向了文件最末尾，则会返回-1，代表文件结束符
         *      带参：读取一组字节的数据，参数为字节数组，用于存储读取到的数据，该方法执行了以下几件事：
         *          1. 获取字节数组的长度
         *          2. 根据字节数组的长度，文件内容指针向后移动，每移动一个字节就对应获取一个字节，存储到字节数组中
         *              如果文件指针指向了文件最末尾，指针就会停止，超出数量的部分不会被成功读取，也不会存储
         *              如果需要使用字节数组的字符串形式表示，可以使用String类的带参构造方法，参数为字节数组、起始索引（0）、成功读取到的字节个数（len）
         *          3. 返回成功读取到的字节个数len，如果调用方法前文件指针已经指向了文件最末尾，再进行调用方法读取，则会返回-1，代表文件结束符
         *  read方法会抛出IOExceptionIO异常，可以声明处理
         */
        System.out.println((char) fileInputStreamC.read()); // T
        int len; // 记录成功读取到的字节个数
        byte[] bytes = new byte[4]; // 记录成功读取到的字节
        /*
         *  以下写法中，判断语句中执行了以下几件事：
         *      1. 获取字节并存入字节数组
         *      2. 将成功获取到的字节个数存入len变量
         *      3. 判断len变量，如果len变量等于-1，代表文件指针已经指向了文件最末尾，没有新的字节可以获取，即可停止获取字节
         */
        while ((len = fileInputStreamC.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, len)); // 将获取到的字节数组转换为字符串的形式
            /*
             *  输出结果：
             *      oast
             *      ie鍦
             *      熶粩
             */
        }

        /*
         *  文件字节输入流使用完毕后需要使用close()方法关闭文件，释放资源
         *  close方法会抛出IOExceptionIO异常，可以声明处理
         */
        fileInputStreamC.close();
    }
}
